package com.ovopark.organize.server.util;


import com.alibaba.fastjson.JSONObject;
import com.github.junrar.Archive;
import com.github.junrar.rarfile.FileHeader;
import com.github.pagehelper.util.StringUtil;
import com.ovopark.organize.server.model.entity.FranchiseeContract;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.compress.archivers.zip.ZipFile;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.math.BigInteger;
import java.net.URL;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.zip.ZipEntry;

public class FileUtil {
    static Logger logger = LoggerFactory.getLogger(FileUtil.class);
    public static List<String> unzip(File zipFile, String descDir) {
        List<String> list = new ArrayList<>();

        try (ZipArchiveInputStream inputStream = getZipFile(zipFile)) {
            File pathFile = new File(descDir);
            if (!pathFile.exists()) {
                pathFile.mkdirs();
            }
            ZipArchiveEntry entry = null;
            while ((entry = inputStream.getNextZipEntry()) != null) {
                String utfName = new String(entry.getName().getBytes(),"gbk");//转换后的结果
                System.out.println(" utfName"+ utfName);
                if (entry.isDirectory()) {
                    File directory = new File(descDir, utfName);
                    directory.mkdirs();
                } else {
                    OutputStream os = null;
                    try {
                        FileOutputStream outputStream = new FileOutputStream(new File(descDir, utfName));

                        os = new BufferedOutputStream(outputStream);
                        //输出文件路径信息
                        logger.info("解压文件的当前路径为:{}", new String[]{descDir + utfName});
                        IOUtils.copy(inputStream, os);
                        list.add(descDir + utfName);
                    } finally {
                        IOUtils.closeQuietly(os);
                    }
                }
            }
            final File[] files = pathFile.listFiles();
            if (files != null && files.length == 1 && files[0].isDirectory()) {
                // 说明只有一个文件夹
                FileUtils.copyDirectory(files[0], pathFile);
                //免得删除错误， 删除的文件必须在/data/demand/目录下。
                boolean isValid = files[0].getPath().contains("/data/www/");
                if (isValid) {
                    FileUtils.forceDelete(files[0]);
                }
            }
            logger.info("******************解压完毕********************");

        } catch (Exception e) {
            logger.error("[unzip] 解压zip文件出错", e);
        }
        return  list;
    }
    private static ZipArchiveInputStream getZipFile(File zipFile) throws Exception {
        return new ZipArchiveInputStream(new BufferedInputStream(new FileInputStream(zipFile)));
    }



    /**
     * 调用org.apache.tools.zip实现解压缩，支持目录嵌套和中文名
     * 也可以使用java.util.zip不过如果是中文的话，解压缩的时候文件名字会是乱码。原因是解压缩软件的编码格式跟java.util.zip.ZipInputStream的编码字符集(固定是UTF-8)不同
     *
     * @param zipFileName
     *            要解压缩的文件
     * @param outputDirectory
     *            要解压到的目录
     * @throws Exception
     */
    public  static Map<String,List<FranchiseeContract>> unZip(File multipartFile,Integer groupId,Integer curUserId) {

       String outputDirectory =multipartFile.getName();
        Map<String,List<FranchiseeContract>> result = new HashMap<>();
        boolean flag = false;
        String zipFileName = multipartFile.getPath();
        try {
            ZipFile zipFile = new ZipFile(zipFileName,"gbk");
            Enumeration e = zipFile.getEntries();
            ZipEntry zipEntry = null;
          //  createDirectory(outputDirectory, "");
            String directory = outputDirectory;
            String subDirectory = "";
            String dir[];
            File fl = new File(directory);
            try {
                if (subDirectory == "" && fl.exists() != true)
                    fl.mkdir();
                else if (subDirectory != "") {
                    dir = subDirectory.replace('\\', '/').split("/");
                    for (int i = 0; i < dir.length; i++) {
                        File subFile = new File(directory + File.separator + dir[i]);
                        if (subFile.exists() == false)
                            subFile.mkdir();
                        directory += File.separator + dir[i];
                    }
                }
            } catch (Exception ex) {
                System.out.println(ex.getMessage());
            }


            while (e.hasMoreElements()) {
                zipEntry = (ZipEntry) e.nextElement();
                // System.out.println("unziping " + zipEntry.getName());
                if (zipEntry.isDirectory()) {
                    String name = zipEntry.getName();
                    name = name.substring(0, name.length() - 1);
                 /*   File f = new File(outputDirectory + File.separator + name);
                    f.mkdir();*/
                  /*  System.out.println("创建目录：" + outputDirectory
                            + File.separator + name);*/
                    String  franchiseeName = "error";
                    List<FranchiseeContract> franchiseeContracts = result.get(franchiseeName);
                    if(franchiseeContracts == null){
                        franchiseeContracts = new ArrayList<>();
                    }
                    FranchiseeContract franchiseeContract = new FranchiseeContract();
                    franchiseeContract.setFileName(name);
                    franchiseeContracts.add(franchiseeContract);
                    result.put(franchiseeName,franchiseeContracts);
                } else {
                    String fileName = zipEntry.getName();
                    if(!fileName.contains("-")){
                        String  franchiseeName = "error";
                        List<FranchiseeContract> franchiseeContracts = result.get(franchiseeName);
                        if(franchiseeContracts == null){
                            franchiseeContracts = new ArrayList<>();
                        }
                        FranchiseeContract franchiseeContract = new FranchiseeContract();
                        franchiseeContract.setFileName(fileName);
                        franchiseeContracts.add(franchiseeContract);
                        result.put(franchiseeName,franchiseeContracts);
                    }else{
                        try {
                            Integer index = fileName.indexOf("-");
                            String franchiseeName = fileName.substring(0,index);
                            String fullPath = "";
                            if(StringUtil.isEmpty(franchiseeName)){
                                franchiseeName = "error";
                            }else{
                                fileName = fileName.substring(index+1 ,fileName.length());
                               SimpleDateFormat format  = new SimpleDateFormat("ddHHmmss");
                                String profix =  format.format(new Date());
                                String filePath = (outputDirectory + File.separator + profix+zipEntry.getName()).replaceAll("\\\\","/");
                            //    String filePath = (outputDirectory + File.separator + zipEntry.getName()).replaceAll("\\\\","/");
                                File f = new File(filePath);
                                f.createNewFile();
                                InputStream in = zipFile.getInputStream((ZipArchiveEntry) zipEntry);
                                FileOutputStream out = new FileOutputStream(f);
                                byte[] by = new byte[1024];
                                int c;
                                while ((c = in.read(by)) != -1) {
                                    out.write(by, 0, c);
                                }
                                out.close();
                                in.close();
                                String suffix = fileName.substring(fileName.lastIndexOf(".")+1);
                                fullPath = OfficeExportUtil.uploadFileToOssNew( f,1, groupId,suffix);
                                f.delete();
                            }
                            List<FranchiseeContract> franchiseeContracts = result.get(franchiseeName);
                            if(franchiseeContracts == null){
                                franchiseeContracts = new ArrayList<>();
                            }
                            FranchiseeContract franchiseeContract = new FranchiseeContract();
                            franchiseeContract.setFileName(fileName);
                            franchiseeContract.setContractUrl(fullPath);
                            franchiseeContracts.add(franchiseeContract);
                            result.put(franchiseeName,franchiseeContracts);
                        }catch (Exception ee){
                            ee.printStackTrace();
                            String  franchiseeName = "error";
                            List<FranchiseeContract> franchiseeContracts = result.get(franchiseeName);
                            if(franchiseeContracts == null){
                                franchiseeContracts = new ArrayList<>();
                            }
                            FranchiseeContract franchiseeContract = new FranchiseeContract();
                            franchiseeContract.setFileName(fileName);
                            franchiseeContracts.add(franchiseeContract);
                            result.put(franchiseeName,franchiseeContracts);
                        }
                    }



                }
                flag = true;
            }
            // 删除 文件
            zipFile.close();
            multipartFile.delete();
            if(fl.exists() ){
                fl.delete();
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return result;
    }
    public static Double GetFileSize(File file){
        Double size = null;
        if(file.exists() && file.isFile()){
            long fileS = file.length();
            DecimalFormat df = new DecimalFormat("#.00");
            String  sizeD = df.format((double) fileS / 1048576);
            size = Double.parseDouble(sizeD);
        }else if(file.exists() && file.isDirectory()){
            size = Double.parseDouble("0");
        }else{
            size =  Double.parseDouble("0");
        }
        return size;
    }

    private static void createDirectory(String directory, String subDirectory) {
        String dir[];
        File fl = new File(directory);
        try {
            if (subDirectory == "" && fl.exists() != true)
                fl.mkdir();
            else if (subDirectory != "") {
                dir = subDirectory.replace('\\', '/').split("/");
                for (int i = 0; i < dir.length; i++) {
                    File subFile = new File(directory + File.separator + dir[i]);
                    if (subFile.exists() == false)
                        subFile.mkdir();
                    directory += File.separator + dir[i];
                }
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
    }

    public static Map<String,List<FranchiseeContract>> unRarFile(File zip, Integer groupId, Integer userId  ) throws IOException {

        Map<String,List<FranchiseeContract>> result = new HashMap<>();

        // 随机生成一个 文件名称 避免重复
        String dstDirectoryPath = zip.getName().substring(zip.getName().lastIndexOf("/")+1,zip.getName().length());

     //   String srcRarPath = "/usr/local/wdsx/lshmPic/"+userId+"/"+System.currentTimeMillis()+"/picture";//路径
     //   String srcRarPath = "D:/test/"+dstDirectoryPath;//路径
        String srcRarPath = zip.getPath();
        //解压到本地，然后 获取 文件夹 名称。然后进入文件夹，读取图片 上传，获得url
        File fileDir = new File(srcRarPath);

        Archive a = null;
        try {
            //源文件 路径+文件名
            a = new Archive(new FileInputStream(new File(srcRarPath)));

            if (a != null) {
                // a.getMainHeader().print(); // 打印文件信息.
                FileHeader fh = a.nextFileHeader();
                while (fh != null) {
                    // 防止文件名中文乱码问题的处理
                    String fileName = fh.getFileNameW().isEmpty() ? fh.getFileNameString() : fh.getFileNameW();

                    String fileDirName = dstDirectoryPath + File.separator + fileName.trim();

                    if (fh.isDirectory()) { // 文件夹
                        File fol = new File(fileDirName);
                        fol.mkdirs();
                    } else { // 文件
                        File out = new File(fileDirName);
                        try {
                            if (!out.exists()) {
                                if (!out.getParentFile().exists()) {// 相对路径可能多级，可能需要创建父目录.
                                    out.getParentFile().mkdirs();
                                }
                                out.createNewFile();
                            }
                            FileOutputStream os = new FileOutputStream(out);
                            a.extractFile(fh, os);
                            os.close();
                            //限制 单张图片大小
                            Double size =  GetFileSize(out);
                            //限制 轮播图的张数，生产企业 企业资质个数 门头照 车间照
                            String preFileName = "";
                            Integer indexNumber = 0;

                        } catch (Exception ex) {
                            ex.printStackTrace();
                        }
                    }
                    fh = a.nextFileHeader();
                }
                a.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
           // logger.error("压缩时，压缩文件格式请选择rar4 "+localFiel.getName()+"dstDirectoryPath"+dstDirectoryPath);
           // result =  realExtract(localFiel,dstDirectoryPath,cmdPath);

            return result;
            //  throw new CommonException("压缩时，压缩文件格式请选择rar4");
        }




        return result;
    }

    private static String getFileNameFromEntryName(String entryName) {
        return entryName.substring(entryName.lastIndexOf("/") + 1);
    }

    private static   String indexType(String fileDirName){
        String indexType = "";
     /*   if(fileDirName.contains(FileHelp.url_is_goods_banner)){
            indexType = FileHelp.url_is_goods_banner;
        }else if(fileDirName.contains(ProductEnterpriseInfo.FILE_CERTIFICATION)){
            indexType = ProductEnterpriseInfo.FILE_CERTIFICATION;
        }else if(fileDirName.contains(ProductEnterpriseInfo.FILE_WORKSHOP_PHOTO)){
            indexType = ProductEnterpriseInfo.FILE_WORKSHOP_PHOTO;
        }else if(fileDirName.contains(ProductEnterpriseInfo.FILE_DOOR_HEAD_PHOTO)){
            indexType = ProductEnterpriseInfo.FILE_DOOR_HEAD_PHOTO;
        }*/
        return indexType;
    }





    /**
     * 采用命令行方式解压文件
     * @param zipFile 压缩文件
     * @param destDir 解压结果路径
     * @param cmdPath WinRAR.exe的路径，也可以在代码中写死
     * @return
     */
    public static   Map<String,List<String>> realExtract(File zipFile, String destDir,String cmdPath) {
        Map<String,List<String>> result = new HashMap<>();

        List<String> list = new ArrayList<>();
        List<String> sizeDobule = new ArrayList<>();
        List<String> moreNumber = new ArrayList<>();
        Map<String,Integer> picNumberMap = new HashMap<>();

        result.put("list",list);
        result.put("sizeDobule",sizeDobule);
        result.put("moreNumber",moreNumber);
        // 解决路径中存在/..格式的路径问题
        destDir = new File(destDir).getAbsoluteFile().getAbsolutePath();
        while(destDir.contains("..")) {
            String[] sepList = destDir.split("\\\\");
            destDir = "";
            for (int i = 0; i < sepList.length; i++) {
                if(!"..".equals(sepList[i]) && i < sepList.length -1 && "..".equals(sepList[i+1])) {
                    i++;
                } else {
                    destDir += sepList[i] + File.separator;
                }
            }
        }

        boolean bool = false;
        if (!zipFile.exists()) {
            return result;
        }

        // 开始调用命令行解压，参数-o+是表示覆盖的意思  cmdPath + " X -o+ " + zipFile + " " + destDir;
        /*  cmdPath = ;*/
        String cmd = cmdPath + " X -o+ " + zipFile + " " + destDir;
        System.out.println(cmd);
        try {
            Process proc = Runtime.getRuntime().exec(cmd);
            proc.getErrorStream();
            proc.getInputStream();
            if (proc.waitFor() != 0) {
                if (proc.exitValue() == 0) {
                    bool = false;
                }
            } else {
                bool = true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("解压" + (bool ? "成功" : "失败"));
        if(bool){
            //解压成功之后，读取此文件夹下所有图片的路径
            String newFilePath = destDir +"/"+ zipFile.getName().substring(0,zipFile.getName().indexOf("."));
            File zipNewFile = new File(newFilePath);
            result = getAllFile(zipNewFile,list,sizeDobule,picNumberMap,moreNumber);
            return result;
        }

        return result;
    }

    private static  Map<String,List<String>> getAllFile(File file, List<String> fileNames,List<String> sizeDobule,Map<String,Integer> picNumberMap,List<String> moreNumber){
        Map<String,List<String>> result = new HashMap<>();
        result.put("list",fileNames);
        result.put("sizeDobule",sizeDobule);
        result.put("moreNumber",moreNumber);
        //判断文件是否存在
        if(!file.exists()){
            System.out.println("文件不存在");
            return  result;
        }
        //当文件只是一个文件夹的时候
        if(!file.isDirectory()){
            if(file.isFile()){
                System.out.println("文件只是一个文件夹");
            }
            return  result;
        }
        File[] listFile = file.listFiles();
        for (File files:listFile ) {
            if(files.isDirectory()){
                //递归
                getAllFile(files,fileNames,sizeDobule,picNumberMap,moreNumber);
            }
            if(files.isFile()){
                //限制 单张图片大小
                Double size =  GetFileSize(files);
                String allPathFile = files.getPath().replaceAll("\\\\","/");
                String preName =allPathFile.split("/picture/")[1];
                if(size ==null || (size !=null && size>2)){
                    sizeDobule.add(preName);
                }else {

                    fileNames.add(allPathFile);
                    //限制 轮播图的张数，生产企业 企业资质个数 门头照 车间照
                    String preFileName = "";
                    Integer indexNumber = 0;
                    String indexType = indexType(files.getPath());
                    if(StringUtil.isNotEmpty(indexType)){
                    /*    indexNumber = preName.lastIndexOf(indexType);
                        preFileName = preName.substring(0,indexNumber);
                        Integer picNum = picNumberMap.get(preFileName);*/
                        String type = indexType+"/";
                        preFileName =  files.getPath().split(type)[0]+"/"+type;
                        preFileName = preFileName.replaceAll("\\\\","/");
                        Integer picNum = picNumberMap.get(preFileName);
                        String pathFileName = preFileName.split("/picture")[1];

                        if(picNum == null){
                            picNum = 1;
                        }else{
                            picNum ++;
                            if(picNum>10){
                                if(moreNumber.contains(pathFileName)){
                                }else{
                                    moreNumber.add(pathFileName);
                                }
                            }
                        }
                        picNumberMap.put(preFileName,picNum);
                    }
                }
            }
        }
        System.out.println("picNumberMap"+ JSONObject.toJSONString(picNumberMap));
        result.put("list",fileNames);
        result.put("sizeDobule",sizeDobule);
        result.put("moreNumber",moreNumber);
        return result;
    }

    public static File download(String urlString, String filename,String savePath) throws Exception {
        // 构造URL
        URL url = new URL(urlString);
        // 打开连接
        URLConnection con = url.openConnection();
        //设置请求超时为5s
        con.setConnectTimeout(5*10000);
        // 输入流
        InputStream is = con.getInputStream();
        // 1K的数据缓冲
        byte[] bs = new byte[1024];
        // 读取到的数据长度
        int len;
        // 输出的文件流
        File sf=new File(savePath);
        if(!sf.exists()){
            sf.mkdirs();
        }
        //sf.getPath()/usr/local/wdsx/lshmPic/188601/1631636234306/picture
        System.out.println("sf.getPath()"+sf.getPath()+"/"+filename);
        // 获取图片的扩展名
        OutputStream os = new FileOutputStream(sf.getPath()+"/"+filename);
        // 开始读取
        while ((len = is.read(bs)) != -1) {
            os.write(bs, 0, len);
        }
        // 完毕，关闭所有链接
        os.close();
        is.close();
        return sf;
    }


    /**
     * 上传完成之后，删除文件
     */

   /* public static List<String> unrar(String rarFileName, String outFilePath) throws Exception {
        List<String> list = new ArrayList<>();
        Archive archive = new Archive(new File(rarFileName));
        if(archive == null){
            throw new FileNotFoundException(rarFileName + " NOT FOUND!");
        }
        if(archive.isEncrypted()){
            throw new Exception(rarFileName + " IS ENCRYPTED!");
        }
        List<FileHeader> files =  archive.getFileHeaders();
        for (FileHeader fh : files) {
            if(fh.isEncrypted()){
                throw new Exception(rarFileName + " IS ENCRYPTED!");
            }
            String fileName = fh.getFileNameString();
            if(fileName != null && fileName.trim().length() > 0){
                String saveFileName = outFilePath+ File.separator+fileName;
                File saveFile = new File(saveFileName);
                File parent =  saveFile.getParentFile();
                if(!parent.exists()){
                    parent.mkdirs();
                }
                if(!saveFile.exists()){
                    saveFile.createNewFile();
                }
                FileOutputStream fos = new FileOutputStream(saveFile);
                try {
                    archive.extractFile(fh, fos);
                } catch (RarException e) {
                    throw e;
                }finally{
                    try{
                        fos.flush();
                        fos.close();
                    }catch (Exception e){
                    }
                }
            }
        }
        return list;
    }*/
    /**
     * 获取单个文件的MD5值！
     * @param file
     * @return
     */
    public static String getFileMD5(File file) {
        if (!file.isFile()) {
            return null;
        }
        MessageDigest digest = null;
        FileInputStream in = null;
        byte buffer[] = new byte[1024];
        int len;
        try {
            digest = MessageDigest.getInstance("MD5");
            in = new FileInputStream(file);
            while ((len = in.read(buffer, 0, 1024)) != -1) {
                digest.update(buffer, 0, len);
            }
            in.close();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        BigInteger bigInt = new BigInteger(1, digest.digest());
        return bigInt.toString(16);
    }





}
